/*
	Written By Pradipna Nepal
	www.pradsprojects.com

	Copyright (C) 2012 Prads Projects
	Please read COPYING.txt included along with this source code for more detail.
	If not included, see http://www.gnu.org/licenses/
*/

#include "libPreProcessor.h"

//Checks all identifiers in token line and replaces const with const value
bool checkForConstants(const vector<IdentTable> *identTable, vector<Token> *tokens, unsigned int i, 
					  unsigned int li);

bool PreProcessor::handleConst(const vector<IdentTable> *identTable, vector<TokenModule> *modules) {
	bool retVal = true;

	for (unsigned int i = 0; i < modules->size(); ++i) {
		for (unsigned int li = 1; li < (*modules)[i].lines.size(); ++li) {
			switch ((*modules)[i].lines[li].lineType) {
				case TL_STRUCT:
					while (li < (*modules)[i].lines.size()) {
						if ((*modules)[i].lines[li].lineType == TL_CLOSE_SCOPE) break;
						++li;
					}
					break;
				case TL_ARRAY_ASSIGNMENT:
				case TL_ASSIGNMENT:
				case TL_CONDITION:
				case TL_FUNCTION_CALL:
				case TL_STRUCT_DECLARE:
				case TL_VAR_DECLARE:
				case TL_INBUILT_FUNCTION_CALL:
					retVal = checkForConstants(identTable, &(*modules)[i].lines[li].tokens, i, li);
					if (!retVal) return retVal;
			}
		}
	}

	return retVal;
}

#define isThereConstant() { \
	for (IdentTable::const_iterator it = rangeIt.first; it != rangeIt.second; ++it) { \
		if ((*tokens)[ti].getValue() == it->second.name) { \
			identFound = true; \
			if (it->second.type == "const"){ \
				(*tokens)[ti].setValue(it->second.initialValue); \
				(*tokens)[ti].setType(TOKEN_DIGIT); \
				break; \
			} \
		} \
	} \
}

bool checkForConstants(const vector<IdentTable> *identTable, vector<Token> *tokens, unsigned int i, 
					   unsigned int li) {
	bool identFound = false;

	for (unsigned int ti = 0; ti < tokens->size(); ++ti) {
		if ((*tokens)[ti].getToken() == TOKEN_IDENTIFIER) {
			unsigned int tokenHash = fnvHash((*tokens)[ti].getValue().c_str(), 
				(*tokens)[ti].getValue().size());
			pair<IdentTable::const_iterator, IdentTable::const_iterator> rangeIt;
			
			//Check in Current Module
			rangeIt = (*identTable)[i].equal_range(tokenHash);
			isThereConstant();

			//If not found in Current Module, check in Main Module
			if (!identFound && (i != 0)) {
				rangeIt = (*identTable)[0].equal_range(tokenHash);
				isThereConstant();
			}

			//If not found in both Modules and is not a function call, generate error
			if (!identFound && ((*tokens)[++ti].getToken() != TOKEN_OPENROUNDBRACKET)) {
				string err;
				err = (*tokens)[ti - 1].getValue() + " - Identifier not found";
				printError(ERROR_UNDECLARED_IDENT, err.c_str());
				return false;
			}
			identFound = false;
		}
	}

	return true;
}